<?php

namespace App\Http\Controllers;


use App\Models\BookInfo;
use App\Models\Category;
use App\Models\DownloadRecord;
use App\Models\File;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use UrlSigner;
use DB;

class DownloadController extends Controller
{
    /**
     * 获取资源下载页
     * @param Request $request
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function getIndex(Request $request)
    {

        $param = $request->all();
        $keyword = $request->input('keyword');
        $catFilter = $request->input('L');
        $child = $request->input('C');
        $categoryId = $request->input('category_id');
        $cost = $request->input('cost');
        $sort = $request->input('sort');
        $specialFilter = false;

        $collectIds = [];
        $boughtIds = [];

        if (Auth::check())
        {
            $userData = Auth::user()->load([
                'collects' => function($query) {
                    $query->select('files.id', 'user_id');
                },
                'bought' => function($query) {
                    $query->select('download_records.id', 'user_id', 'file_id');
                }
            ]);
            $collectIds = array_pluck($userData->collects->toArray(), 'id');
            $boughtIds = array_pluck($userData->bought->toArray(), 'file_id');
        }

        $categorys = Category::select('id', 'name')
            ->where('p_id', 0)
            ->with(['children' => function($query) {
                $query->select('id', 'name', 'p_id');
            }])
            ->get();

        if (count($categorys) > 0)
        {
            if ($categoryId)
            {
                $cat = Category::select('id', 'name')->find($categoryId);
            } else {
                if (!$keyword) {
                    $categoryC = $categorys[0]->children;
                    if (count($categoryC) > 0) {
                        $cat = $categoryC[0];
                        $categoryId = $cat->id;
                    }
                }
            }

            if (!isset($cat) || !$cat)
            {
                $filter = null;
            } else {
                $cat->load(['children' => function($q) {
                    $q->select('id', 'name', 'p_id')
                        ->with(['children' => function($query) {
                            $query->select('id', 'name', 'p_id');
                        }]);
                }]);
                $filter = $cat->children;
                $filterArray = array_filter(array_pluck($filter->toArray(), 'children'));
                if (count($filterArray) == 0)
                {
                    $filter = Category::select('id', 'name')
                        ->with(['children' => function($q) {
                            $q->select('id', 'name', 'p_id');
                        }])
                        ->where('id', $categoryId)
                        ->get();
                    $specialFilter = true;
                }
            }
        }

        $searchArr = [];
        $multipleArr = [];
        $twoMultipleArr = [];
        $delVal = null;

        if (!isset($param['C']))
        {
            $param['C'] = null;
            $selectArr = [];
        } elseif (empty($param['C']) && $keyword && !$categoryId && !$catFilter && !$child) {
            $selectArr = [];
        } else {
            $arr = array_filter(explode(',', $child));
            $uniqueArr = array_unique($arr);
            $cancelSelect = array_diff_assoc($arr, $uniqueArr);

            //重复选择某一个分类则取消选择
            if ($cancelSelect)
            {
                foreach ($cancelSelect as $key => $value)
                {
                    $val = Category::select('id', 'name', 'p_id')
                        ->with('parent')
                        ->find($value);

                    if (strstr($val->parent->name, '阶段'))
                    {
                        $valChildren = $val->children->pluck('id')->toArray();
                        foreach ($valChildren as $key => $child)
                        {
                            unset($uniqueArr[array_search($child, $uniqueArr)]);
                        }
                    }
                    unset($uniqueArr[array_search($value, $uniqueArr)]);
                }
            }

            if ($catFilter)
            {
                $catFilter = $filter->find($catFilter);
                if ($catFilter)
                {
                    $catFilterChildren = $catFilter->children;
                    foreach ($catFilterChildren as $key => $catFilterChild)
                    {
                        if (strstr($catFilter->name, '阶段'))
                        {
                            $unsetIds = $catFilterChild->children->pluck('id');
                            foreach ($unsetIds as $k => $unsetId)
                            {
                                unset($uniqueArr[array_search($unsetId, $uniqueArr)]);
                            }
                        }
                        unset($uniqueArr[array_search($catFilterChild->id, $uniqueArr)]);
                    }
                }
            }

            //单个分类只允许选择一个
            foreach ($filter as $key => $item)
            {
                $itemChildren = $item->children;
                $itemIds = $itemChildren->pluck('id')->toArray();
                $intersectArr = array_values(array_intersect($uniqueArr, $itemIds));
                $intersectNum = count($intersectArr);

                if (strstr($item->name, '阶段') && $intersectNum == 1)
                {
                    $stageIds = Category::whereIn('p_id', $itemIds)->pluck('id')->toArray();
                    $intersectArr = array_values(array_intersect($uniqueArr, $stageIds));
                    $intersectNum = count($intersectArr);
                }

                if ($intersectNum > 1)
                {
                    foreach ($intersectArr as $k => $value)
                    {
                        $intSub = array_search($value, $intersectArr);

                        if ($intSub != ($intersectNum - 1))
                        {
                            if (strstr($item->name, '阶段'))
                            {
                                $valueIds = Category::where('p_id', $value)->pluck('id')->toArray();
                                $delIds = array_intersect($uniqueArr, $valueIds);
                                foreach ($delIds as $delId)
                                {
                                    unset($uniqueArr[array_search($delId, $uniqueArr)]);
                                }
                            }
                            $sub = array_search($value, $uniqueArr);
                            unset($uniqueArr[$sub]);
                        }
                    }
                }

                if (array_intersect($uniqueArr, $itemIds) && strstr($item->name, '阶段'))
                {
                    $stageId = implode(array_intersect($uniqueArr, $itemIds));

                    $grades = Category::where('p_id', $stageId)->select('id', 'name')->get();
                    $item->grades = $grades;

                    $gradeIds = $grades->pluck('id')->toArray();
                    $delVal = $stageId;

                    if (!array_intersect($uniqueArr, $gradeIds))
                        $multipleArr = $gradeIds;
                }
            }
            $searchArr = array_merge($searchArr, $uniqueArr);
            $selectArr = $uniqueArr;
            $param['C'] = implode($uniqueArr, ',');
        }

        if (count($searchArr) == 0 && count($multipleArr) == 0 && $categoryId)
        {
            $arr = Category::select('id', 'p_id')->get()->toArray();
            $twoMultipleArr = array_pluck($this->getMenuTree($arr, $categoryId), 'id');
            $twoMultipleArr[] = intval($categoryId);
        }

        if ($delVal)
            unset($searchArr[array_search($delVal, $searchArr)]);

        $files = File::select('id', 'title', 'product_id', 'category', 'cost', 'price', 'size', 'type', 'star', 'download')
            ->whereNotNull('local')
            ->with([
                'product' => function($query) {
                    $query->select('products.id', 'uuid', 'name', 'summary', 'cover');
                }
            ]);
        if ($keyword)
            $files = $files->where('title', 'like', '%' . $keyword . '%');

        $files = $files->whereHas('product', function ($query) use ($categoryId, $searchArr, $multipleArr, $twoMultipleArr){
            if (!$searchArr && !$multipleArr && $twoMultipleArr)
            {
                $query->whereHas('categorys', function ($q) use ($twoMultipleArr) {
                        $q->whereIn('product_categorys.category_id', $twoMultipleArr);
                    });
            }

            if (count($searchArr) != 0 || count($multipleArr) > 0)
            {
                if ($searchArr)
                {
                    $query->whereHas('categorys', function ($q) use ($searchArr) {
                        $q->whereIn('category_id', $searchArr);
                    }, '=', count($searchArr));
                }

                if ($multipleArr)
                {
                    $query->whereHas('categorys', function ($q) use ($multipleArr) {
                        $q->select('product_categorys.category_id');
                        $q->whereIn('category_id', $multipleArr);
                    });
                }
            }

            $query->select('products.id', 'name')->where('auditing_status', 'online');
        });

        if ($cost == 'free' || $cost == 'charge') {
            $files = $files->where('cost', $cost);
        }

        if ($cost == 'bought')
        {
            $files = $files->whereIn('id', $boughtIds);
        }

        if ($sort == 'new' || !$sort)
        {
            $files = $files->orderBy('created_at', 'desc');
        } elseif ($sort == 'hot')
        {
            $files = $files->orderBy('download', 'desc');
        }

        $files = $files->paginate(3);



        foreach ($files as $key => $file)
        {
            unset($file->product_id);
            unset($file->product->id);
            $file->is_star = false;
            $file->is_bought = false;

            if (in_array($file->id, $collectIds))
                $file->is_star = true;

            if (in_array($file->id, $boughtIds))
                $file->is_bought = true;

            $files[$key] = $file;
        }

        unset($param['L']);
        unset($param['_token']);

        return view('download.index', [
            'param' => $param,
            'categorys' => $categorys,
            'filter' => $filter,
            'selectArr' => $selectArr,
            'files' => $files,
            'categoryId' => $categoryId,
            'specialFilter' => $specialFilter
        ]);
    }

    /**
     * 购买并下载资源
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse|void
     */
    public function postDownload(Request $request)
    {
        $fileId = $request->input('file_id');
        $file = File::select('id', 'title', 'category', 'size', 'type', 'local', 'cost', 'price', 'download')
            ->find($fileId);

        if (!$file)
            return abort(404);

        if (empty($file->local))
            return abort(500);

        $user = Auth::user();

        if (!$user->bought()->where('file_id', $fileId)->first())
        {
            if ($file->cost == 'charge') {
                if ($user->coin < $file->price)
                {
                    return response()->json([
                        'status' => 'error',
                        'code' => 10001,
                        'msg' => '金币不足',
                        'data' => [
                            'my_coin' => $user->coin,
                            'need_coin' => $file->price
                        ]
                    ]);
                }
                $user->coin -= $file->price;
                $user->save();
            }

            $record = new DownloadRecord();
            $record->order_sn = Carbon::now()->format('YmdHis'). random_int(1000000, 9999999);
            $record->file_id = $file->id;
            $record->user_id = $user->id;
            $record->file_title = $file->title;
            $record->pay_amount = $file->cost == 'free' ? 0 : $file->price;
            $record->is_pay = 'finish';
            $record->save();
        }

        if ($request->method() == 'POST')
        {
            $downloadUrl = UrlSigner::sign(route('downloadFile', ['file_id' => $fileId]), Carbon::now()->addMinute(10));
            return response()->json([
                'status' => 'success',
                'data' => [
                    'url' => $downloadUrl
                ]
            ]);
        }

        $filePath = $file->local;

        $file->download += 1;
        $file->save();

        //获取链接后缀
        $suffix = pathinfo($filePath, PATHINFO_EXTENSION);
        if ($suffix)
        {
            $fileName = $file->title . '.' .$suffix;
            return response()->download(realpath(base_path('public/uploads')) . '/' .$filePath, $fileName);
        } else {
            return response()->download(realpath(base_path('public/uploads')) . '/' . $filePath);
        }
    }

    /**
     * 获取试读音视频列表
     * @param Request $request
     * @return mixed
     */
    public function getTryOutList(Request $request)
    {

        $q = $request->input('q');
        $type = $request->input('type');

        $files = File::where('title', 'like', "%$q%")
            ->where('category', $type)
            ->paginate(null, ['id', 'title as text']);

        return $files;
    }
}